Some programming languages provide the ability to declare methods that contain code in types other than classes. For example, Java provides the ability to declare default and abstract methods within a reference type known as an interface. A default method within an interface consists of a method signature and a method body. In contrast, an abstract method within an interface consists of a method signature but no method body.
Classes implementing an interface are able to inherit default methods without declaring a method with a matching method signature or providing a method body. For example, if a method with signature void m( ) is declared as a default method in an interface, then classes implementing the interface may inherit the default method void m( ) without including additional code. If the function void m( ) was instead declared as an abstract method, then no method body would be included in the interface. As a result, any class implementing the collection interface would be responsible for providing the code for the method void m( ) by declaring a method that overrides the abstract method in the interface. Abstract methods may thus incur a significant cost on developers writing classes implementing a particular interface. Default methods mitigate these costs by allowing the same method body, declared within an interface, to be shared across multiple classes implementing the interface. Any changes to the interface's default methods are propagated to the classes implementing the interface without the need to modify the classes.
Conflicts may arise when a class implements different interfaces that declare default methods having the same method signature. For example, two or more interfaces may include a default method with the same signature void m( ) and different method bodies. If a class implements both interfaces, then method invocation of m( ) of the class may create ambiguity as to which of the default methods was intended to be executed.
Proxying may lead to further ambiguity when default methods conflict. Proxying allows method calls on an object that implements an interface to be intercepted. The intercepted method calls are dispatched to an object, referred to as a method call processor. The method call processor determines how to handle an intercepted method call. For example, the method call processor may record or modify the method call. Additionally or alternatively, the method call processor may dispatch the method call to another underlying object that implements the interfaces. If a method invocation to a conflicting default method is intercepted, then the method call processor may not behave as intended.
The approaches described in this section are approaches that could be pursued, but not necessarily approaches that have been previously conceived or pursued. Therefore, unless otherwise indicated, it should not be assumed that any of the approaches described in this section qualify as prior art merely by virtue of their inclusion in this section.